<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>设计模式——装饰者模式</title>
    <script type="application/javascript" charset="UTF-8" src="../../common/CommonUtils.js"></script>
    <script type="application/javascript" charset="UTF-8">
        /**
         * 装饰者模式 : 透明的把原始对象包装到具有同样接口的新的对象中
         * 实现同样的接口
         * 要有子类
         */

        // 先构造一个接口实例
        var CarInterface = new WL.Interface(CarInterface, ['getPrice','assemble']);

        // 定义一个原始类
        var Car = function (car) {
            // 用来让子类继承，使子类多一个父类的引用
            this.car = car;
            // 检测接口
            WL.Interface.ensureImplements(this,CarInterface);
        };

        // 父类实现接口
        Car.prototype = {
            // 还原构造器
            constructor : Car ,
            getPrice : function () {
                return 20000;
            },
            assemble : function () {
                document.write('组装汽车....');
            }
        };

        // 现在的新需求是，顾客可以根据需要，选择为车加装饰物，比如：车灯、车载冰箱...
        // 通常的做法可以是，在定义一个子类，继承父类，然后添加子类自己的方法，
        // 但是通常情况下，这些新的装饰物是会影响到父类中的方法的，比如这里车的价格

        // 一个更好解决方式就是采用装饰者模式
        var LightDecorator = function (car) {
            // 借用构造函数继承父类


            // 上面的代码相当于如下：继承了父类的构造器
            // 用来让子类继承，使子类多一个父类的引用
            // this.car = car;
            // 检测接口
            // WL.Interface.ensureImplements(this,CarInterface);
        };

        // 原型继承，只继承了父类的原型方法
        WL.extend(LightDecorator, Car);

        // 子类实现接口中的方法
        LightDecorator.prototype = {
            // 还原构造器
            constructor : LightDecorator ,
            getPrice : function () {
                return this.car.getPrice() + 1000;
            },
            assemble : function () {
                document.write('组装车灯...');
            }
        };

        var car = new Car();
        document.write(car.getPrice());
        document.write('<hr/>');
        car.assemble();
        document.write('<hr/>');

        var car = new LightDecorator(car);
        document.write(car.getPrice());
        document.write('<hr/>');
        car.assemble();
        document.write('<hr/>');

    </script>
</head>
<body>

</body>
</html>